#include "debug.h"
#include "usb_device.h"
#include "usbd_cdc_if.h"

#define Dealy_MS(ms) HAL_Delay(ms)

extern USBD_HandleTypeDef hUsbDeviceFS;

#ifdef USE_USB_PRTINF

#define Buffer_size 64


void USB_Printf(char *fmt, ...)
{
  unsigned char Printf_buf[Buffer_size] = {0};
	va_list args;
	va_start(args, fmt);
	vsnprintf((char *)Printf_buf, Buffer_size, (char *)fmt, args);
	va_end(args);
	CDC_Transmit_FS(Printf_buf, sizeof(Printf_buf));
}

#endif

void JumpToBootloader(void)
{
    uint32_t i = 0;
    void (*SysMemBootJump)(void);        /* 声明一个函数指针 */
    __IO uint32_t BootAddr = 0x1FFF0000; /* F407系统BootLoader地址 */

    /* 重启前指示 */
    CDC_Transmit_FS("\n\n\rJump to BootLoader\n\n\r", 30);
    USBD_Stop(&hUsbDeviceFS);
    /* 关闭全局中断 */
    __set_PRIMASK(1);
    /* 关闭滴答定时器，复位到默认值 */

    // USBD_LL_
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL  = 0;
    /* 设置所有时钟到默认状态，使用HSI时钟 */
    // RCC_DeInit();
    /* 关闭所有中断，清除所有中断挂起标志 */
    for (i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }
    /* 使能全局中断 */
    __set_PRIMASK(0);
    /* 跳转到系统BootLoader，首地址是MSP，地址+4是复位中断服务程序地址 */
    SysMemBootJump = (void (*)(void))(*((uint32_t *)(BootAddr + 4)));
    /* 设置主堆栈指针 */
    __set_MSP(*(uint32_t *)BootAddr);
    /* 在RTOS工程，这条语句很重要，设置为特权级模式，使用MSP指针 */
    __set_CONTROL(0);
    USBD_LL_Reset(&hUsbDeviceFS);
    /* 跳转到系统BootLoader */
    SysMemBootJump();
    /* 跳转成功的话，不会执行到这里，用户可以在这里添加代码 */
    // while (1)
    // {
    // }
}
